package com.diver.flinkdemo.utils;


import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.ByteArrayRequestEntity;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpStatus;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.ssl.SSLContextBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.util.Iterator;
import java.util.Map;

/**
 * http请求工具类
 */
public class HttpUrlClient {
    private static final String APPLICATION_JSON = "application/json;charset=utf-8";
    private static final String CONTENT_TYPE_TEXT_JSON = "text/json";
    private static final int CONNECTION_TIMEOUT = 20000;
    private static final String CHARCODE = "UTF-8";
    private static Logger logger = LoggerFactory.getLogger(HttpUrlClient.class);

    // 连接管理器
    protected static PoolingHttpClientConnectionManager pool;

    // 请求配置
    private static RequestConfig requestConfig;

    static {

        try {
            // System.out.println("初始化HttpClientTest~~~开始");
            SSLContextBuilder builder = new SSLContextBuilder();
            builder.loadTrustMaterial(null, new TrustSelfSignedStrategy());
            SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(builder.build());
            // 配置同时支持 HTTP 和 HTPPS
            Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create().register("http", PlainConnectionSocketFactory.getSocketFactory()).register("https", sslsf).build();
            // 初始化连接管理器
            pool = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
            // 将最大连接数增加到200，实际项目最好从配置文件中读取这个值
            pool.setMaxTotal(200);
            // 设置最大路由
            pool.setDefaultMaxPerRoute(2);
            // 根据默认超时限制初始化requestConfig
            int socketTimeout = 10000;
            int connectTimeout = 10000;
            int connectionRequestTimeout = 10000;
            requestConfig = RequestConfig.custom().setConnectionRequestTimeout(connectionRequestTimeout).setSocketTimeout(socketTimeout).setConnectTimeout(connectTimeout).build();

            // System.out.println("初始化HttpClientTest~~~结束");
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (KeyStoreException e) {
            e.printStackTrace();
        } catch (KeyManagementException e) {
            e.printStackTrace();
        }

        // 设置请求超时时间
        requestConfig = RequestConfig.custom().setSocketTimeout(50000).setConnectTimeout(50000).setConnectionRequestTimeout(50000).build();
    }

    public static CloseableHttpClient getHttpClient() {

        CloseableHttpClient httpClient = HttpClients.custom()
                // 设置连接池管理
                .setConnectionManager(pool)
                // 设置请求配置
                .setDefaultRequestConfig(requestConfig)
                // 设置重试次数
                .setRetryHandler(new DefaultHttpRequestRetryHandler(0, false)).build();

        return httpClient;
    }

    public HttpUrlClient() {

    }

    /**
     * Using GET method.
     *
     * @param url         The remote URL.
     * @param queryString The query string containing parameters
     * @return Response string.
     * @throws Exception
     */
    public static String httpGet(String url, String queryString) throws Exception {
        String responseData = null;

        if (queryString != null && !queryString.equals("")) {
            url += "?" + queryString;
        }
        logger.info("请求地址:" + url);
        HttpClient httpClient = new HttpClient();
        httpClient.getHostConfiguration().setProxy("10.45.19.17", 56666);
        GetMethod httpGet = new GetMethod(url);
        httpGet.getParams().setParameter("http.socket.timeout", new Integer(CONNECTION_TIMEOUT));

        try {
            int statusCode = httpClient.executeMethod(httpGet);
            if (statusCode != HttpStatus.SC_OK) {
                System.err.println("HttpGet Method failed: " + httpGet.getStatusLine());
            }
            // Read the response body.
            responseData = httpGet.getResponseBodyAsString();
        } catch (Exception e) {
            throw new Exception(e);
        } finally {
            httpGet.releaseConnection();
            httpClient = null;
        }

        return responseData;
    }

    /**
     * Using POST method.
     *
     * @param url         The remote URL.
     * @param queryString The query string containing parameters
     * @return Response string.
     * @throws Exception
     */
    public static String httpPost(String url, String queryString) throws Exception {
        String responseData = null;
        HttpClient httpClient = new HttpClient();
        httpClient.getHostConfiguration().setProxy("10.45.19.17", 56666);
        PostMethod httpPost = new PostMethod(url);
        httpPost.addParameter("Content-Type", "application/x-www-form-urlencoded");
        httpPost.getParams().setParameter("http.socket.timeout", new Integer(CONNECTION_TIMEOUT));

        if (queryString != null && !queryString.equals("")) {
            //          httpPost.setRequestEntity(new ByteArrayRequestEntity(queryString.getBytes()));
            httpPost.setRequestEntity(new ByteArrayRequestEntity(queryString.getBytes("UTF-8")));
        }

        try {
            int statusCode = httpClient.executeMethod(httpPost);
            if (statusCode != HttpStatus.SC_OK) {
                logger.error("HttpPost Method failed: " + httpPost.getStatusLine());
            }
            responseData = httpPost.getResponseBodyAsString();
        } catch (Exception e) {
            e.printStackTrace();
            throw new Exception(e);
        } finally {
            httpPost.releaseConnection();
            httpClient = null;
        }
        logger.info("返回信息:" + responseData);
        return responseData;
    }

    public static String doPost(String reqUrl, Map<String, String> parameters, String charset) {
        HttpURLConnection urlConn = null;
        try {
            urlConn = sendPost(reqUrl, parameters);
            String responseContent = getContent(urlConn, charset);
            logger.info("doPost result:" + responseContent);
            return responseContent.trim();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        } finally {
            if (urlConn != null) {
                urlConn.disconnect();
                urlConn = null;
            }
        }
    }

    public static String doPost3(String reqUrl, Map<String, String> parameters) {
        if (parameters != null && !parameters.isEmpty()) {
            String generatorParamString = generatorParamStringWithoutCode(parameters);
            reqUrl += (reqUrl.contains("?") ? "&" : "?") + generatorParamString;
            parameters.clear();
        }
        return doPost(reqUrl, parameters, CHARCODE);
    }

    public static String doPost(String reqUrl, Map<String, String> parameters) {
        /*if (parameters != null && !parameters.isEmpty()) {
            String generatorParamString = generatorParamStringWithoutCode(parameters);
            reqUrl += (reqUrl.contains("?") ? "&" : "?") + generatorParamString;
            parameters.clear();
        }*/
        return doPost(reqUrl, parameters, CHARCODE);
    }

    public static String doGet(String reqUrl, Map<String, String> parameters, String charset) {
        HttpURLConnection urlConn = null;
        try {
            urlConn = sendGet(reqUrl, parameters);
            String responseContent = getContent(urlConn, charset);
            return responseContent.trim();
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage(), e);
        } finally {
            if (urlConn != null) {
                urlConn.disconnect();
                urlConn = null;
            }
        }
    }

    public static String doGet(String reqUrl, Map<String, String> parameters) {
        return doGet(reqUrl, parameters, CHARCODE);
    }

    private static String getContent(HttpURLConnection urlConn, String charset) {
        int code;
        try {
            code = urlConn.getResponseCode();

            String responseContent = null;
            InputStream in = null;
            if (code == HttpURLConnection.HTTP_OK) {
                in = urlConn.getInputStream();
            } else {
                in = urlConn.getErrorStream();
            }
            BufferedReader rd = new BufferedReader(new InputStreamReader(in, charset));
            String tempLine = rd.readLine();
            StringBuffer tempStr = new StringBuffer();
            String crlf = System.getProperty("line.separator");
            while (tempLine != null) {
                tempStr.append(tempLine);
                tempStr.append(crlf);
                tempLine = rd.readLine();
            }
            responseContent = tempStr.toString();
            rd.close();
            in.close();
            return responseContent;
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage(), e);
        }
    }

    private static HttpURLConnection sendPost(String reqUrl, Map<String, String> parameters) {
        HttpURLConnection urlConn = null;
        String urlStr = reqUrl;
        try {
            String params = generatorParamString(parameters);
            if (params != null && !"".equals(params)) {
                urlStr += (reqUrl.contains("?") ? "&" : "?") + params;
            }
            URL url = new URL(urlStr);
            logger.info("请求地址:" + urlStr);
//            System.out.println("get:"+urlStr);
            urlConn = (HttpURLConnection) url.openConnection();
            urlConn.setRequestMethod("POST");
            urlConn.setConnectTimeout(1000);
            urlConn.setReadTimeout(1000);
            urlConn.setDoInput(true);
            urlConn.setDoOutput(true);
            byte[] b = params.getBytes();
            urlConn.getOutputStream().write(b, 0, b.length);
            urlConn.getOutputStream().flush();
            urlConn.getOutputStream().close();
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage(), e);
        }
        return urlConn;
    }

    private static HttpURLConnection sendGet(String reqUrl, Map<String, String> parameters) {
        HttpURLConnection urlConn = null;

        String urlStr = reqUrl;
        String parmas = generatorParamString(parameters);
        if (StringUtils.isNotBlank(parmas)) {
            urlStr = reqUrl + "?" + parmas;
        }
        try {
//            System.out.println("get:"+urlStr);
            URL url = new URL(urlStr);
            urlConn = (HttpURLConnection) url.openConnection();
            urlConn.setRequestMethod("GET");
            urlConn.setConnectTimeout(1000);
            urlConn.setReadTimeout(1000);
            urlConn.setDoInput(true);
            urlConn.setDoOutput(true);
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage(), e);
        }
        return urlConn;
    }

    public static String generatorParamString(Map<String, String> parameters) {
        StringBuffer params = new StringBuffer();
        if (parameters != null) {
            for (Iterator<String> iter = parameters.keySet().iterator(); iter.hasNext(); ) {
                String name = iter.next();
                String value = parameters.get(name);
                params.append(name + "=");
                try {
                    if (StringUtils.isNotBlank(value)) {
                        params.append(URLEncoder.encode(value, CHARCODE));
                    }
                } catch (UnsupportedEncodingException e) {
                    throw new RuntimeException(e.getMessage(), e);
                } catch (Exception e) {
                    String message = String.format("'%s'='%s'", name, value);
                    throw new RuntimeException(message, e);
                }
                if (iter.hasNext()) {
                    params.append("&");
                }
            }
        }
        logger.debug("参数:" + params.toString());
        return params.toString();
    }

    private static String generatorParamStringWithoutCode(Map<String, String> parameters) {
        StringBuffer params = new StringBuffer();
        if (parameters != null) {
            for (Iterator<String> iter = parameters.keySet().iterator(); iter.hasNext(); ) {
                String name = iter.next();
                String value = parameters.get(name);
                params.append(name + "=");
                params.append(value);
                if (iter.hasNext()) {
                    params.append("&");
                }
            }
        }
        logger.debug("参数:" + params.toString());
        return params.toString();
    }

    public static String httpPostWithJSON(String url, String paramsJson) throws Exception {
        logger.info("httpPostWithJSON===>url:{}", url);
        if (StringUtils.isNotBlank(paramsJson)) {
            logger.info("paramsJson:{}", paramsJson.length() < 300 ? paramsJson : paramsJson.substring(0, 300) + "...");
        }
        HttpPost httpPost = new HttpPost(url);// 创建httpPost
        // 设置参数
        if (paramsJson != null && paramsJson.trim().length() > 0) {
            StringEntity stringEntity = new StringEntity(paramsJson, "UTF-8");
            httpPost.setHeader("Content-Type", APPLICATION_JSON);
            httpPost.setEntity(stringEntity);
            CloseableHttpClient httpClient = null;
            CloseableHttpResponse response = null;
            // 响应内容
            String responseContent = null;
            try {
                // 创建默认的httpClient实例.
                httpClient = getHttpClient();
                // 配置请求信息
                httpPost.setConfig(requestConfig);
                // 得到响应
                response = httpClient.execute(httpPost);
                // 得到响应实例
                HttpEntity entity = response.getEntity();
                // 判断响应状态
                Integer statusCode = response.getStatusLine().getStatusCode();
                if (HttpStatus.SC_OK == statusCode) {
                    InputStream is = entity.getContent();
                    // 读取输入流，即返回文本内容
                    StringBuffer sbResult = new StringBuffer();
                    BufferedReader br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
                    String line = null;
                    while ((line = br.readLine()) != null) {
                        sbResult.append(line);
                    }
                    responseContent = sbResult.toString();
                    if (StringUtils.isNotBlank(paramsJson) && responseContent.length() > 300) {
                        logger.info("httpPostWithJSON==>responseContent:{}", responseContent.substring(0, 300) + "...");
                    } else {
                        logger.info("httpPostWithJSON==>responseContent:{}", responseContent);
                    }
                    return responseContent;
                }
            } catch (Exception e) {
                logger.error("httpPostWithJSON error", e);
            } finally {
                if (response != null) {
                    response.close();
                }
            }
        }
        return null;
    }
}
